const _pick = require("lodash/pick");
const _assign  = require("lodash/assign");
const _isEmpty  = require("lodash/isEmpty");
import Taro from "@tarojs/taro";
// import API_CONFIG from "../service/api";
import request from "./request";

function assert(condition: any, msg: string): void {
  if (!condition) {
    throw new Error(`[Apior] ${msg}`);
  }
}

const REQUEST_BASEURL =
  "https://www.baidu.com";

class MakeApi {
  api: object;
  constructor(options: object) {
    this.api = {};
    this.apiBuilder(options);
  }

  apiBuilder({
    sep = "|",
    config = {},
    mock = false,
    debug = false,
    mockBaseURL = "",
    baseURL = REQUEST_BASEURL,
  }) {
    Object.keys(config).map(namespace => {
      this._apiSingleBuilder({
        namespace,
        mock,
        mockBaseURL,
        baseURL,
        sep,
        debug,
        config: config[namespace],
      });
    });
  }

  /**
   *
   *
   * @param {*} {
   *     namespace,
   *     sep = "|",
   *     config = [],
   *     mock = false,
   *     debug = false,
   *     mockBaseURL = "",
   *     baseURL = REQUEST_BASEURL,
   *     redirectLoginPage = REDIRECT_PAGE,
   *   }
   * @memberof MakeApi
   */
  _apiSingleBuilder({
    namespace,
    sep = "|",
    config = [],
    mock = false,
    debug = false,
    mockBaseURL = "",
    baseURL = REQUEST_BASEURL,
  }) {
    config.forEach(api => {
      const {
        name,
        desc,
        params,
        method,
        mockEnable,
        path,
        mockPath,
        absolute,
        dealLoginSelf,
        dealErrorSelf,
        limitParams = true
      } = api;
      const isMock: boolean =
        process.env.NODE_ENV === "production" ? false : mock || mockEnable;
      const url: string = isMock ? mockPath : path;
      baseURL = isMock ? mockBaseURL : baseURL;

      if (debug) {
        // debug 测试
        assert(name, `${url} :接口name属性不能为空`);
        assert(url.indexOf("/") === 0, `${url} :接口路径path，首字符应为/`);
      }

      Object.defineProperty(this.api, `${namespace}${sep}${name}`, {
        value(outerParams: object, outerOptions: object): any {
          let dataV = {};
          if (_isEmpty(outerParams)) {
            dataV = params;
          } else if (limitParams) {
            dataV = _pick(
              _assign({}, params, outerParams),
              Object.keys(params)
            );
          } else {
            dataV = outerParams;
          }
          const optionsV = {
            url,
            desc,
            baseURL,
            method,
            absolute,
            dealLoginSelf,
            dealErrorSelf
          };
          const platformId = Taro.getStorageSync("platformId") || 894;
          const platformObj = { platform_id: platformId };
          return request(
            _normoalize(
              _assign(optionsV, outerOptions),
              Object.assign(dataV, platformObj)
            )
          );
        },
      });
    });
  }
}
// 可以在outerOption里传入需要传入路由中的值，默认为apiParams
function _normoalize(options, data) {
  // 添加直接在url上传参的逻辑
  const apiParams = options.apiParams;
  const url = options.url;
  options.url = generateUrl(url, apiParams);
  // 正常参数逻辑
  options.data = data;
  return options;
}

function generateUrl(url, params) {
  const reg = /:\w+/gi;
  if (reg.test(url)) {
    return url.replace(reg, value => {
      const key = value.substring(1);
      if (params[key]) {
        return params[key];
      } else {
        throw new Error("您的接口为动态接口，传入的参数中必须有与接口对应字段");
      }
    });
  }
  return url;
}

export default MakeApi;
